#pragma once
#ifndef H_OPTIMIZATIONFACTORY
#define H_OPTIMIZATIONFACTORY
#include "precompiled.h"
#include "character.h"
#include "item.h"
namespace weo
{
    namespace engine
    {
        namespace optimization
        {
            class OptimizationFactory
            {
            private:
                typedef void * (OptimizationFactoryFn) ();
                std::map<std::string,OptimizationFactoryFn*> m_OptimizerMap;
                std::map<unsigned int, std::string> m_PerformanceMap;
                std::vector<std::vector<const weo::engine::item::Item*>> m_Items;
                double m_Itemscount;
                double m_LockedItemscount;
                bool m_Locks[weo::engine::Slotcount];
                // <<singleton>>
                static OptimizationFactory* s_Factory;
            public:
                static OptimizationFactory* getInstance();
                template<typename ClassName>
                static ClassName *CallFactory(std::string name = "", unsigned int count = 0)
                {
                    return (ClassName *)getInstance()->callFactory(name, count);
                }
                static void RegisterOptimizer(std::string name, unsigned int count, OptimizationFactoryFn* pFunction)
                {
                    getInstance()->registerOptimizer(name,count,pFunction);
                }
                static void SetItems(const std::vector<std::vector<const weo::engine::item::Item*>>& items)
                {
                    getInstance()->setItems(items);
                }
                static void SetLocks(bool *locks)
                {
                    getInstance()->setLocks(locks);
                }
                void setItems(const std::vector<std::vector<const weo::engine::item::Item*>>& items)
                {
                    m_Items = items;
                    m_Itemscount = 1;
                    google::sparse_hash_set<unsigned int> validset;
                    for(unsigned int i = 0;i<weo::engine::Slotcount;i++)
                    {
                        if(!m_Locks[i])
                        {
                            unsigned int size = 0;
                            for(unsigned int k = 0;k<items[i].size();k++)
                            {
                                if(items[i][k]->Unique())
                                {
                                    if(validset.count(items[i][k]->Id()) == 0)
                                    {
                                        validset.insert(items[i][k]->Id());
                                        size++;
                                    }
                                }
                                else
                                {
                                    size++;
                                }
                            }
                            m_Itemscount *=size;
                        }
                    }
                }
                void setLocks(bool *locks)
                {
                    for(int i = 0;i<weo::engine::Slotcount;i++)
                    {
                        m_Locks[i] = locks[i];
                    }
                }
                void* callFactory(std::string name = "", unsigned int count = 0);
                void registerOptimizer(std::string name, unsigned int count, OptimizationFactoryFn* pFunction);
                template<typename ClassName>
                static void* FactoryFunction()
                {
                    return new ClassName;
                }
                OptimizationFactory();
            };
        };
    };
};
#endif